//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//	File		 :	Parse.cpp
//	Contents	 :	Source file for class Parse
//	Creation Date:	22/12/1999
//	Last Modified:	23/12/1999	lg
//	tabs width	 :	every 4 characters
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888


#include <iostream>
#include <string>
#include <cassert>
#include <vector>
#include "parse.h"
#include "msfresource.h"
#ifdef _MFC_VER	// mfc specific code to follow
#include "../common/mfc_stdcpp.h"
#else
#include "../common/nonmfc_stdcpp.h"
#endif


//_______________________________________________________________________________________
//
//	Handle call backs from the parsing engine when there are errors or warnings
//	This object just dumps the stuff to the standard streams
//		Last modified: lg 23/12/1999
//
//_______________________________________________________________________________________
bool CConsole_ParseMessageCallback::Warning(const std::string& description, unsigned /*lineNum*/)
{
	std::cerr << description;
	return false;
}

void CConsole_ParseMessageCallback::Error(const std::string& description, unsigned /*lineNum*/)
{
	std::cerr << description;
}

void CConsole_ParseMessageCallback::LengthsUnEqError(const std::string& s, const CSequence& seq)
{
	std::cerr << s;
	std::cerr << "Not all of the sequences parsed had the same lengths.\r\n";
	unsigned len = seq.GetNamesMaxLen();

	//write header
	len = std::max(7U, len);
	std::cerr	<< "Names: "
				<< std::string(len - 7, ' ')
				<< "Lengths:" << std::endl;
	for (int i = seq.Count() - 1; i >= 0; --i)
	{
		std::cerr	<< seq.Names[i]
					<< std::string(len - seq.Names[i].length(), ' ')
					<< seq.Data[i].length()
					<< std::endl;
	}
}





//_______________________________________________________________________________________
//
//	DoErrMsg
//
//		Displays error message in a message box
//		msgID is the resource id of the error message
//		num is the line number if positive
//		Last modified: lg 23/12/1999
//
//_______________________________________________________________________________________
void CParse::DoErrMsg(unsigned msgID, int num, const char* token)
{
	std::string msg;
	LoadString(msg, m_InvalidFileMsg);

	std::string tmp;
	LoadString(tmp, msgID);

	char  buf[256];
	sprintf(buf, tmp.c_str(), abs(num), token);
	msg += buf;
	MessageCallback.Error(msg, (num > 0) ? num : 0);
}

bool CParse::DoWarnMsg(unsigned msgID, int num, const char* token)
{
	std::string tmp;
	LoadString(tmp, msgID);
	char  buf[256];
	sprintf(buf, tmp.c_str(), abs(num), token);
	std::string msg;
	LoadString(msg, m_ErrFileMsg);
	msg += buf;
	//"\r\nDo you wish to proceed regardless?"
	LoadString(tmp, IDS_ERR_PROCEEDQUERY);
	msg += tmp;
	if (MessageCallback.Warning(msg, (num > 0) ? num : 0))
		return true;
	return false;
}

void CParse::ParseErrLength(const CSequence& seq)
{
	std::string msg;
	LoadString(msg, m_InvalidFileMsg);
	MessageCallback.LengthsUnEqError(msg, seq);
}


//_______________________________________________________________________________________
//
//	MatchNames
//
//		Internal function
//		Checks to see if the passed name matches any of those in the vector
//		Returns index or -1 if not found
//		Assumes that names occur successively and in order so
//			minimizes search by starting from lastmatch + 1
//		Last modified: lg 23/12/1999
//
//_______________________________________________________________________________________
int CParse::MatchNames(const CSequence::vec_str& names, const std::string& testName, int& last_Match)
{
	if (!names.size())
		return -1;

	assert (last_Match < (int)names.size());

	// assume that Sequence Data is in sequence
	++last_Match;
	last_Match %= names.size();
	int new_Match = last_Match;
	assert(new_Match >=0);
	do
	{
		if (testName == names[new_Match])
		{
			last_Match = new_Match;
			return new_Match;
		}

		// increment index and wrap around
		++new_Match;
		new_Match %= names.size();
	}
	while(last_Match != new_Match);

	--last_Match;
	return -1;
}


